package com.dk.filter;

import com.alibaba.fastjson.JSONObject;
import com.dk.data.Result;
import com.dk.em.ResultEnum;
import com.dk.util.JwtUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Component
public class LoginFilter extends ZuulFilter {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JwtUtil jwtUtil;

    private static List<String> ignoreURL = new ArrayList<>();
    static {
        ignoreURL.add("/order/api/order/addbath");
        ignoreURL.add("/freemarker/api");
        ignoreURL.add("/recommend/api/test");
    }

    /**
     * 配置过滤类型，有四种不同生命周期的过滤器类型
     * 1. pre：路由之前
     * 2. routing：路由之时
     * 3. post：路由之后
     * 4. error：发送错误调用
     * @return
     */
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    /**
     * 我们网关可以写多个过滤器，哪个过滤器先执行，根据
     * 这个方法数字大小越小越先执行
     * */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 表示是否开启过滤器
     * */
    @Override
    public boolean shouldFilter() {

        RequestContext  ctx =RequestContext.getCurrentContext();//判断上一层拦截是否通过
        if(!ctx.sendZuulResponse()){//上一层拦截不通过

            System.out.println(" 上一层拦截不通过,不开启拦截");//该拦截不需要开启

            return false;

        }

        /** 登录 两种方式 一个另一个网关 一个自己写拦截逻辑*/
        RequestContext currentContext = RequestContext.getCurrentContext();
        //获取request域对象
        HttpServletRequest request = currentContext.getRequest();
        String requestURI = request.getRequestURI();

        if (ignoreURL.contains(requestURI)){
            return false;
        }
        return false;
    }

    /**
     * 过滤
     * */
    @Override
    public Object run() throws ZuulException {
        //获取当前线程请求上下文类
        RequestContext currentContext = RequestContext.getCurrentContext();
        //获取request域对象
        HttpServletRequest request = currentContext.getRequest();
        /** 通过请求头获取token*/
        String authToken = request.getHeader("authToken");
        //获取参数
//        String userName = request.getParameter("userName");
        //校验用户名是否存在，如果不存在，说明用户未登录，不放过(UserDTO)redisTemplate.boundValueOps(authToken).get() == null)
        if(authToken == null || "".equals(authToken)) {
            //设置响应域对象
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseStatusCode(400);
            //获取response
            HttpServletResponse response = currentContext.getResponse();
            try {
                response.setContentType("text/html;charset=utf-8");
//                response.getWriter().write("用户未登录，无法访问服务,请先登录");
                Result result = Result.response(ResultEnum.NOLOGIN);
                response.getWriter().write(JSONObject.toJSONString(result));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            try {
                Claims claims = jwtUtil.parseJwt(authToken);
                claims.getId();
                claims.getSubject();
            }catch (Exception e){
                //设置响应域对象
                currentContext.setSendZuulResponse(false);
                currentContext.setResponseStatusCode(400);
                //获取response
                HttpServletResponse response = currentContext.getResponse();
                try {
                    response.setContentType("text/html;charset=utf-8");
//                response.getWriter().write("用户未登录，无法访问服务,请先登录");
                    Result result = Result.response(ResultEnum.NOLOGIN);
                    response.getWriter().write(JSONObject.toJSONString(result));
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }

        return null;
    }
}
